Skip to content

o/snapstate, o/devicestate: update hooks to let devicestate own what results in a seed-refresh - #17006

Merged
sergiocazzolato merged 2 commits into
canonical:masterfrom
andrewphelpsj:seed-refresh-devicestate-ownership
May 25, 2026
Merged

o/snapstate, o/devicestate: update hooks to let devicestate own what results in a seed-refresh#17006
sergiocazzolato merged 2 commits into
canonical:masterfrom
andrewphelpsj:seed-refresh-devicestate-ownership

Conversation

@andrewphelpsj

Copy link
Copy Markdown
Member

This moves some code around so that devicestate owns more about what results in a seed refresh. Next PR will make it so that we consider snaps that are present in the seed, as well as what snaps are in the model, when deciding whether or not to refresh the seed.

@codecov

codecov Bot commented Apr 30, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.48148% with 52 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.04%. Comparing base (0e217e5) to head (f62d38b).

Files with missing lines Patch % Lines
overlord/devicestate/devicestate.go 61.03% 21 Missing and 9 partials ⚠️
overlord/snapstate/seed.go 61.40% 15 Missing and 7 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master   #17006      +/-   ##
==========================================
- Coverage   79.14%   79.04%   -0.10%     
==========================================
  Files        1366     1369       +3     
  Lines      192385   191772     -613     
  Branches     2465     2465              
==========================================
- Hits       152266   151590     -676     
- Misses      30998    31038      +40     
- Partials     9121     9144      +23     
Flag Coverage Δ
unittests 79.04% <61.48%> (-0.10%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Apr 30, 2026

Copy link
Copy Markdown

Mon May 25 17:52:04 UTC 2026
The following results are from: https://github.com/canonical/snapd/actions/runs/26286756037

Failures:

Preparing:

  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/fde-auth-support-on-hybrid
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-fde-all-key-databases:db
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-fde-recovery-keys
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-xkb-kcmdline
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-fde-all-key-databases:dbx
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-fde-all-key-databases:pk
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/hybrid-fde-all-key-databases:kek

Executing:

  • openstack-ext:ubuntu-18.04-64:tests/nested/manual/devmode-snaps-can-run-other-snaps
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller-real:plain
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller-real:encrypted
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller-real:seeded
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller-real:preseed
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller-real:partial
  • openstack-ext:ubuntu-26.04-64:tests/nested/manual/muinstaller
  • openstack:ubuntu-24.04-64:tests/main/snap-seccomp-syscalls

Skipped tests from snapd-testing-skip

If you wish to have any of the below tests run in your PR, in your PR description, add 'unskip:' followed by a copy-and-pasted list (without variants) of the below tests you wish to run (unskip plus test list must be valid yaml)

  • openstack:arch-linux-64:tests/main/snapctl-no-wait
  • openstack:debian-12-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-20.04-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-20.04-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-24.04-64:tests/main/i18n
  • openstack:ubuntu-24.04-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-24.04-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-flag-restart
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:audio_record_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:audio_record_timespan_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:audio_record_timespan_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_actioned_by_other_pid_always_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_actioned_by_other_pid_always_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_not_actioned_by_other_pid_single_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_multiple_not_actioned_by_other_pid_single_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_write_chmod_same_fd_single_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_write_chmod_same_path_single_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:create_write_write_same_path_single_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:download_file_conflict
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:download_file_defaults
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:download_file_safer
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:read_single_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:read_single_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:special_characters
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:timespan_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:timespan_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:write_read_multiple_actioned_by_other_pid_allow_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:write_read_multiple_actioned_by_other_pid_deny_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:write_single_allow
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-integration-tests:write_single_deny
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-prompt-restoration
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_allow_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_allow_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_allow_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_allow_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_deny_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_deny_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_deny_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:audiorecord_deny_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_allow_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_allow_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_allow_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_allow_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_deny_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_deny_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_deny_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:camera_deny_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_allow_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_allow_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_allow_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_allow_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_deny_forever
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_deny_session
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_deny_single
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-smoke:home_deny_timespan
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-snapd-startup
  • openstack:ubuntu-26.04-64:tests/main/apparmor-prompting-support
  • openstack:ubuntu-26.04-64:tests/main/i18n
  • openstack:ubuntu-26.04-64:tests/main/interfaces-requests-activates-handlers
  • openstack:ubuntu-26.04-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-26.04-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-core-18-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-core-18-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-core-20-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-core-20-64:tests/main/snapctl-no-wait
  • openstack:ubuntu-core-24-64:tests/main/snapctl-is-ready
  • openstack:ubuntu-core-24-64:tests/main/snapctl-no-wait

@pedronis pedronis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed this needs some cleaning up

Comment thread overlord/devicestate/devicestate.go Outdated
}
added[snapsup.SnapName()] = true

if !snapsup.ComponentExclusiveOperation {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as discussed this shows that the responsibility boundary crossing here is not great, some of this building up of sets of snapups and compups belongs to snapstate really

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reworked this a bit, hopefully things are better now.

@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch 3 times, most recently from 65fa590 to a4502a7 Compare May 6, 2026 18:14
@andrewphelpsj
andrewphelpsj requested a review from pedronis May 6, 2026 18:14
@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch from a4502a7 to 4ab7583 Compare May 11, 2026 08:43
@bboozzoo
bboozzoo requested a review from Copilot May 11, 2026 09:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the seed-refresh integration so that devicestate (rather than snapstate) owns the policy for which snap refreshes participate in a seed refresh, and also owns updating an in-flight seed-refresh change with late prerequisite candidates. This aligns with the stated goal of centralizing “what results in a seed-refresh” in devicestate ahead of adding more selection criteria in a follow-up PR.

Changes:

  • Introduces a snapstate.SeedRefreshCandidate data model and changes the SeedRefreshTasks hook to accept candidates and return which snaps were selected.
  • Adds a new snapstate.UpdateSeedRefreshChange hook so devicestate can update an existing seed-refresh change with late prerequisite candidates.
  • Updates seed-refresh-related tests to assert on the new candidate flow and hook behavior (including component-exclusive candidates).

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
overlord/snapstate/snapstate_update_test.go Updates seed-refresh update tests to use candidate-based hooks and validate initial/prerequisite candidate selection.
overlord/snapstate/snapstate_test.go Adds shared test hook helpers (mockSeedRefreshHooks) and installs them in test setup.
overlord/snapstate/seed.go Refactors snapstate seed-refresh wiring to pass candidate structs into devicestate and to merge late prerequisites via the new hook.
overlord/snapstate/reboot_test.go Adjusts reboot/seed-refresh tests to validate component-exclusive candidate behavior with the new hook API.
overlord/snapstate/handlers.go Updates prerequisite-refresh flow to use the updated seed-refresh merge helper signature.
overlord/devicestate/devicestate.go Implements candidate filtering/selection and late-change updates in devicestate; wires new hook in cross-manager init.
overlord/devicestate/devicestate_test.go Updates devicestate unit tests for the new SeedRefreshTasks signature and adds coverage for UpdateSeedRefreshChange.
overlord/devicestate/devicestate_systems_test.go Updates systems test to use the new SeedRefreshTasks signature and assert selected snaps.

Comment thread overlord/snapstate/seed.go Outdated
Comment on lines 232 to 234
// seed-refresh task graph by adding its setup tasks to create-recovery-system,
// joining its task set to the seed-refresh lanes, and ensuring seed creation
// tasks depend on the prerequisite refresh tasks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe indeed the comment should mention the bi of logic in devicestate that this is using?

@andrewphelpsj andrewphelpsj left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comments from in-person review in the sprint.

Comment thread overlord/snapstate/seed.go Outdated
InstanceName string
// SnapSetupTasks are the snap tasks that should be considered as inputs to
// recovery system creation. Will be empty for component-only refreshes.
SnapSetupTasks []string

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SnapSetupTaskIDs

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a re-refresh test to cover the double create-recovery-system case

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I checked, we have TestUpdateWithGoalSeedRefreshReRefreshCreatesSecondSeed which creates this scenario, and then the tests in devicestate that actually cover skipping already done seed-creation tasks.

@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch from 4ab7583 to 4653a39 Compare May 18, 2026 14:23

@pedronis pedronis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks, small remark

Comment thread overlord/snapstate/seed.go Outdated
Comment on lines 232 to 234
// seed-refresh task graph by adding its setup tasks to create-recovery-system,
// joining its task set to the seed-refresh lanes, and ensuring seed creation
// tasks depend on the prerequisite refresh tasks.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe indeed the comment should mention the bi of logic in devicestate that this is using?

Comment thread overlord/snapstate/seed.go
Comment thread overlord/devicestate/devicestate.go Outdated
return setTaskRecoverySystemSetup(create, setup)
}

func seedRefreshIncludesSnap(dctx snapstate.DeviceContext, instanceName string) bool {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this check make more sense in snapstate? or maybe it could be exported to avoid the awkwardness or returning nil in UpdateSeedRefreshChange if snap isn't part of the seed refresh?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked on MM, but the main motivations for this living here is because we'll need to check the seed to make this decisions, which would be very hard/awkward to do from snapstate.

@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch 2 times, most recently from 2dbd0e4 to 7510e18 Compare May 20, 2026 15:42
@andrewphelpsj andrewphelpsj added Run nested The PR also runs tests inluded in nested suite Auto rerun spread Auto reruns spread up to 4 times in non-draft PRs w/ >=1 approval and <20 fails in any fund. system labels May 20, 2026
@andrewphelpsj andrewphelpsj reopened this May 20, 2026
@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch from 7510e18 to dc3a6c7 Compare May 21, 2026 14:39
@andrewphelpsj
andrewphelpsj force-pushed the seed-refresh-devicestate-ownership branch from dc3a6c7 to f62d38b Compare May 22, 2026 12:05
@sergiocazzolato
sergiocazzolato merged commit b12a6f5 into canonical:master May 25, 2026
743 of 782 checks passed
ZeyadYasser pushed a commit to ZeyadYasser/snapd that referenced this pull request Jun 3, 2026
…results in a seed-refresh (canonical#17006)

* overlord/snapstate: migrate seed-refresh TODO tests

* o/snapstate, o/devicestate: update hooks to let devicestate own what results in a seed-refresh
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Auto rerun spread Auto reruns spread up to 4 times in non-draft PRs w/ >=1 approval and <20 fails in any fund. system Run nested The PR also runs tests inluded in nested suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants